<!--
 * @Description: 搜索输入框 支持搜索历史、搜索推荐
 * @Version: 1.0
 * @Autor: hekai
 * @Date: 2022-10-22 14:40:26
-->
<template>
  <div>
    <a-input
      v-model="searchValue"
      v-bind="$attrs"
      @change="searchValueChange"
      @focus="onFocus"
      @blur="onBlur">
    </a-input>
    <!-- 展开条件：1.处于焦点 2.用户prop传了searchRecommendList -->
    <div v-show="isFocus && searchRecommendList.length !== 0" class="option-box">
      <transition name="fade">
        <div>
          <!-- 搜索推荐 -->
          <ul class="list-body">
            <a-spin :spinning="loading">
              <li class="list-item" v-for="item in searchRecommendList" @click.stop="selectItem(item)" :key="item.key">
                <span v-html="brightenKeyword(item.label, searchValue)"></span>
              </li>
            </a-spin>
          </ul>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>

  export default {
    name: 'PSearchInput',
    props: {
      // 搜索框值
      value: {
        type: [String, undefined],
        required: true
      },
      loadData: {
        type: Function,
        default: () => {
          return new Promise(resolve => resolve([]))
        }
      }
    },
    watch: {
      // 双向绑定，实现父组件v-modal改值时，能影响this.searchValue
      value(newVal) {
        this.searchValue = newVal
      }
    },
    data() {
      return {
        searchValue: this.value,
        isFocus: false,
        loading: false,
        // 搜索栏的数组。类似于百度输入后下面弹出的搜索提示
        // 实例：[{label:'推荐语1',key:'d033dbb5-9d66-49f8-ba56-7462e104174a'}...]
        searchRecommendList: []
      }
    },
    model: {
      prop: 'value',
      event: 'change'
    },
    mounted() {
      window.addEventListener('click', () => {
        this && this.onBlur && this.onBlur()
      })
    },
    methods: {
      // 搜索框的值改变监听事件
      searchValueChange() {
        if (this.searchValue !== '') {
          // 搜索值不为空 触发搜索推荐
          // 输入防抖，快速输入的时候避免多次请求
          if (this.searchQueryTimer) {
            clearTimeout(this.searchQueryTimer)
          }
          this.searchQueryTimer = setTimeout(() => {
            this.$emit('recommend', this.searchValue)
            // 请求搜索推荐接口
            this.loadData(this.searchValue).then(list => {
              this.searchRecommendList = JSON.parse(JSON.stringify(list))
              this.setFocus(true)
            }).catch(() => {
              this.searchRecommendList = []
              this.setFocus(false)
            })
          }, 200)
        }

        this.$emit('change', this.searchValue)
      },
      brightenKeyword(val, keyword) {
        let res = val
        if (val && keyword) {
          res = val.replaceAll(keyword, `<span style="color: #008AFF;">${keyword}</span>`)
        }
        return res
      },
      onFocus() {
        this.setFocus(true)
      },
      onBlur() {
        // 因为没有捕捉到onBlur的事件，所以导致数据最后是true
        // 加个定时器，防止选择后焦点消失无法触发selectItem事件
        this.isFocus && this.setFocus(false)
      },
      setFocus(val) {
        this.tempFocus = val
        if (this.timer) clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          this.isFocus = this.tempFocus
          console.log('setFocus->' + this.isFocus)
        }, 300)
      },
      selectItem(item) {
        this.$emit('change', item.label)
        this.searchRecommendList = []
        this.setFocus(false)
      }
    }
  }
</script>

<style scoped lang="less">

.blue-bar {
  display: block;
  width: 2px;
  height: 20px;
  background: #008AFF;
  border-radius: 2px;
  position: relative;
  top: 1px;
  right: 10px;
}

.option-box {
  position: relative;
  top: -11px;

  .list-body {
    z-index: 2000;
    position: absolute;
    top: calc(100% + 11px);

    width: calc(100%);
    min-height: 50px;
    max-height: 400px;

    padding: 0;
    background: #fff;
    border-radius: 6px 6px 6px 6px;

    box-shadow: 0 2px 12px 1px rgba(0, 0, 0, 0.06);
    //border: 1px solid #D7D7D7;

    li.list-item {
      display: flex;
      justify-content: space-between;
      align-items: center;

      list-style-type: none;
      font-size: 14px;
      z-index: 2002;
      color: #848D92;

      width: 100%;
      height: 32px;
      min-height: 32px;
      padding: 6px 0 6px 20px;
      cursor: pointer;

      .delete-icon {
        display: none;
        width: 16px;
        height: 16px;
        margin-right: 10px;
      }

      &:hover {
        background: rgba(0, 138, 255, 0.2);
        color: #303030;

        .delete-icon {
          display: block;
        }
      }
    }

    li.delete-all {
      cursor: pointer;
      margin: 0 10px;
      padding: 10px 0;
      font-size: 14px;
      color: #303030;
      text-align: right;
      border-top: 1px solid #ececec;
    }
  }
}

/deep/ .ant-input-wrapper {
  height: 100%;
}

/deep/ .ant-input-search {
  height: 100%;
}

/deep/ .ant-input-group-addon {
  height: 100%;
  border-radius: 0 6px 6px 0;
}

/deep/ .ant-input:focus {
  -webkit-box-shadow: none;
  box-shadow: none;
  border-color: #d9d9d9;
}

/deep/ .ant-input-search-enter-button + .ant-input-group-addon .ant-input-search-button {
  width: 140px;
  height: 100%;
  font-weight: 600;
  font-size: 16px;
  border-radius: 0 6px 6px 0;
  border: 1px solid #303030;
}

/deep/ .ant-input-group > .ant-input-affix-wrapper:not(:last-child) .ant-input {
  height: 100%;
  font-size: 16px;
  padding-left: 20px;
  border: 1px solid #303030;
  border-left-width: 0;
}

/deep/ .ant-input-group-addon:first-child {
  height: 100%;
  font-size: 16px;
  background-color: #fff;
  border-radius: 6px 0 0 6px;
  border: 1px solid #303030;
  border-right-width: 0;
}
</style>
